package com.zysdev.openglbeautydemo.filter

import android.graphics.Bitmap
import android.graphics.SurfaceTexture
import android.opengl.EGL14
import android.opengl.GLES20
import android.opengl.GLSurfaceView
import android.os.Environment
import androidx.camera.core.Preview
import androidx.lifecycle.LifecycleOwner
import com.zysdev.openglbeautydemo.R
import com.zysdev.openglbeautydemo.filter.addFilter.BeautyFilter
import com.zysdev.openglbeautydemo.filter.addFilter.GiftFilter
import com.zysdev.openglbeautydemo.filter.addFilter.SoulFilter
import com.zysdev.openglbeautydemo.filter.addFilter.SplitScreenFilter
import java.io.File
import java.io.IOException
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

class CameraRender : GLSurfaceView.Renderer, Preview.OnPreviewOutputUpdateListener,
    SurfaceTexture.OnFrameAvailableListener {

    private var cameraView: CameraView? = null

    private var surfaceTexture: SurfaceTexture? = null
    private val textures: IntArray = IntArray(1)
    private var cameraFilter: CameraFilter? = null

    //渲染到屏幕上
    private var showScreenFilter: ShowScreenFilter? = null

    //    private var split2ScreenFilter: SplitScreenFilter? = null
//    private var split4ScreenFilter: SplitScreenFilter? = null
//    private var soulFilter: SoulFilter? = null
    private var beautyFilter: BeautyFilter? = null
    private var giftFilter: GiftFilter? = null

    private var mtx = FloatArray(16)

    private var mediaRecorder: MediaRecorder? = null

    constructor(cameraView: CameraView) {
        this.cameraView = cameraView
        val lifecycleOwner = cameraView.context as LifecycleOwner
        //打开摄像头
        CameraHelper(lifecycleOwner, this)

    }

    // 打开摄像头后，摄像头预览到的数据通过接口回调到这里
    override fun onUpdated(output: Preview.PreviewOutput?) {
        //获取到摄像头的预览数据，数据在surfaceTexture里
        surfaceTexture = output?.surfaceTexture

    }

    override fun onSurfaceCreated(p0: GL10?, p1: EGLConfig?) {
//      让SurfaceTexture与Gpu共享一个数据源0-31
        //绑定摄像头和GPU，此时会在GPU创建一个内存
        surfaceTexture?.attachToGLContext(textures[0])

        //当有数据过来时的回调
        surfaceTexture?.setOnFrameAvailableListener(this)
        val context = cameraView!!.context

        cameraFilter = CameraFilter(context)
//        soulFilter = SoulFilter(context)
        showScreenFilter = ShowScreenFilter(context)
//        split2ScreenFilter = SplitScreenFilter(context, R.raw.base_vert, R.raw.split2_frag)
//        split4ScreenFilter = SplitScreenFilter(context, R.raw.base_vert, R.raw.split4_frag)
//        split3ScreenFilter = ShowScreenFilter(context)
        beautyFilter = BeautyFilter(context)


        val file = File(Environment.getExternalStorageDirectory(), "opengl_filter_output.mp4")
        if (file.exists()) {
            file.delete()
        }

        val path = file.absolutePath
        mediaRecorder = MediaRecorder(context, path, EGL14.eglGetCurrentContext(), 480, 640)
    }

    override fun onSurfaceChanged(p0: GL10?, width: Int, height: Int) {
        showScreenFilter?.setSize(width, height)
        cameraFilter?.setSize(width, height)
        beautyFilter?.setSize(width, height)
//        split2ScreenFilter?.setSize(width, height)
//        split4ScreenFilter?.setSize(width, height)
//        soulFilter?.setSize(width, height)
    }

    //这里的线程是GLThread
    //当GLSurfaceView重新渲染时requestRender()，会回调到这里
    override fun onDrawFrame(p0: GL10?) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        GLES20.glEnable(GLES20.GL_BLEND);
        //快速生成mipmap贴图
        GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
        //开启GL的混合模式，即图像叠加
        GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA)
        //        更新数据
        surfaceTexture?.updateTexImage()
        //将图像的矩阵信息保存到mtx中
        surfaceTexture?.getTransformMatrix(mtx)

        cameraFilter?.setTransformMatrix(mtx)

        //1、将摄像头数据传到FBO中
        //传入一个原纹理图层id，cameraFilter返回的是FBO的纹理图层ID，可以对FBO的纹理图层进行操作
        //fbo里此时是摄像头的画面数据，摄像头被FBO拦截了，不会输出到屏幕，屏幕没画面
        var fboTextureId: Int = cameraFilter?.onDraw(textures[0])!!
//        Log.e("---", "----fboTextureId=$fboTextureId")

        //2、处理FBO数据，加特效
        //美颜
        if (beautyFilter != null) {
            fboTextureId = beautyFilter!!.onDraw(fboTextureId)
        }
        //贴图：水印
//        if (giftFilter != null) {
//            fboTextureId = giftFilter!!.onDraw(fboTextureId)
//        }
        //(1)分两屏
//        fboTextureId = split2ScreenFilter?.onDraw(fboTextureId)!!
        //(2)分四屏
//        fboTextureId = split4ScreenFilter?.onDraw(fboTextureId)!!
//        (3)灵魂出窍
//        fboTextureId = soulFilter!!.onDraw(fboTextureId)


        //3、将处理完的FBO纹理图层渲染到屏幕
        fboTextureId = showScreenFilter!!.onDraw(fboTextureId)


        //4、将数据录制到本地文件或发送出去
        //注意如果要取FBO数据，需要创建EGL环境（opengl线程），才能调用Opengl函数
        mediaRecorder?.fireFrame(fboTextureId, surfaceTexture!!.timestamp)

    }


    //SurfaceTexture里有数据时
    override fun onFrameAvailable(p0: SurfaceTexture?) {
        //让cameraView手动刷新
        cameraView?.requestRender()
    }


    fun startRecord(speed: Float) {
        try {
            mediaRecorder?.start(speed)
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    fun stopRecord() {
        mediaRecorder?.stop()
    }


    fun enableBeauty(isChecked: Boolean) {
        if (cameraView != null) {
            cameraView!!.queueEvent(Runnable {
                //添加滤镜需要在GL线程
                if (isChecked) {
                    beautyFilter = BeautyFilter(cameraView!!.context)
                    beautyFilter!!.setSize(cameraView!!.width, cameraView!!.height)
                } else {
                    beautyFilter?.release()
                    beautyFilter = null
                }
            })
        }
    }

    fun showOrGoneGift(isShow: Boolean = true, bitmap: Bitmap? = null) {
        if (cameraView != null) {
            cameraView!!.queueEvent(Runnable {
                if (isShow && bitmap != null) {
                    //添加滤镜需要在GL线程
                    giftFilter = GiftFilter(cameraView!!.context, bitmap)
                    giftFilter!!.setSize(cameraView!!.width, cameraView!!.height)
                }else{
                    giftFilter?.release()
                    giftFilter = null
                }
            })
        }
    }
}